/*
    Copyright (C) 2011 Rodrigo Castaño - Hugo Arregui, FuDePAN

    This file is part of the Prot-Filer Library

    Prot-Filer is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Prot-Filer is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Prot-Filer.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef ANGLES_DATA_H
#define ANGLES_DATA_H

#include <vector>
#include "prot-filer/definitions.h"

namespace prot_filer
{

struct AnglesMapping
{
    AnglesMapping(unsigned int nres) :
        fis(),
        sis(),
        nres(nres)
    {}
    AngleId set_mapping(const AngleValue fi, const AngleValue si)
    {
        const AngleId result = AngleId(fis.size());
        fis.push_back(fi);
        sis.push_back(si);
        return result;
    }
    AngleValue get_fi_value(const AngleId id) const
    {
        return fis[id];
    }
    AngleValue get_si_value(const AngleId id) const
    {
        return sis[id];
    }
    unsigned int get_mapping_size() const
    {
        return fis.size();
    };
    unsigned int get_nres() const
    {
        return nres;
    };
    bool operator==(const AnglesMapping& angles_mapping) const
    {
        bool result = nres == angles_mapping.nres;
        result = result && (fis.size() == angles_mapping.fis.size());
        result = result && (sis.size() == angles_mapping.sis.size());
        for (unsigned int i(0); result && i < fis.size() ; ++i)
        {
            result = result && (fis[i] == angles_mapping.fis[i]);
            result = result && (sis[i] == angles_mapping.sis[i]);
        }
        return result;
    }
private:
    std::vector<AngleValue> fis;
    std::vector<AngleValue> sis;
    uint32_t nres;
};

struct AngleIdPair
{
    AngleId fi;
    AngleId si;
    AngleIdPair() :
        fi(),
        si()
    {}
    AngleIdPair(AngleId fi, AngleId si) :
        fi(fi),
        si(si)
    {}
};

struct AnglesData
{
    AnglesData(unsigned int nres) :
        nres(nres),
        angles(new AngleIdPair[nres - 1]),
        angles_mapping(NULL)
    {}
    AnglesData(unsigned int nres, AnglesMapping* angles_mapping) :
        nres(nres),
        angles(new AngleIdPair[nres - 1]),
        angles_mapping(angles_mapping)
    {}
    ~AnglesData()
    {
        delete[] angles;
    }
    AnglesData(const AnglesData& other) :
        nres(other.nres),
        angles(new AngleIdPair[other.nres - 1]),
        angles_mapping(NULL)
    {
        operator=(other);
    }
    const AnglesMapping& get_angles_mapping() const
    {
        return *angles_mapping;
    }
    AnglesData& operator=(const AnglesData& other)
    {
        if (other.nres != nres)
        {
            throw "operator= was called with a structure that has a different number of residues.";
        }
        for (int i = 0 ; i < int(nres) - 1; ++i)
        {
            angles[i] = other.angles[i];
        }
        angles_mapping = other.angles_mapping;
        return *this;
    }
public:
    unsigned int nres;
    AngleIdPair* angles;
    ATOM seed[3];
private:
    AnglesMapping* angles_mapping;
};

}
#endif
